package cc.shacocloud.mirage.restful.bind.converter.json;

import cc.shacocloud.mirage.restful.http.MediaType;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;

/**
 * HttpMessageConverter，可以读和写 JSON 使用 Jackson 2.x的 objectMapping。
 * 此转换器可用于绑定到有类型的 bean 或无类型的 HashMap 实例。
 * 默认情况下，该转换器支持 application/json 和 application/*+json 的 UTF-8 字符集。
 * 默认构造函数使用 Jackson2ObjectMapperBuilder 提供的默认配置。
 */
public class JacksonHttpMessageConverter extends AbstractJacksonHttpMessageConverter {
    
    @Nullable
    private String jsonPrefix;
    
    /**
     * 使用由{@link Jackson2ObjectMapperBuilder}提供的默认配置构造一个新的{@link JacksonHttpMessageConverter}
     */
    public JacksonHttpMessageConverter() {
        this(Jackson2ObjectMapperBuilder.json().build());
    }
    
    /**
     * 使用自定义{@link ObjectMapper}构造一个新的{@link JacksonHttpMessageConverter}。
     * 您可以使用{@link Jackson2ObjectMapperBuilder}轻松地构建它。
     *
     * @see Jackson2ObjectMapperBuilder#json()
     */
    public JacksonHttpMessageConverter(ObjectMapper objectMapper) {
        super(objectMapper, MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
    }
    
    
    /**
     * 指定用于此视图的JSON输出的自定义前缀。默认是没有的。
     *
     * @see #setPrefixJson
     */
    public void setJsonPrefix(@Nullable String jsonPrefix) {
        this.jsonPrefix = jsonPrefix;
    }
    
    /**
     * 指示此视图的JSON输出是否应该以")]}'，"为前缀。默认是假的。
     * <p>
     * 以这种方式为JSON字符串添加前缀可以帮助防止JSON劫持。
     * 前缀使字符串作为脚本在语法上无效，因此它不能被劫持。
     * 在将字符串解析为JSON之前，应该去除这个前缀。
     *
     * @see #setJsonPrefix
     */
    public void setPrefixJson(boolean prefixJson) {
        this.jsonPrefix = (prefixJson ? ")]}', " : null);
    }
    
    
    @Override
    protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
        if (this.jsonPrefix != null) {
            generator.writeRaw(this.jsonPrefix);
        }
    }
    
}
